package org.xurui.sxl.protocol.command.impl;

import lombok.extern.slf4j.Slf4j;
import org.jetlinks.core.message.CommonDeviceMessage;
import org.jetlinks.core.message.DeviceMessage;
import org.jetlinks.core.message.codec.EncodedMessage;
import org.jetlinks.core.message.codec.FromDeviceMessageContext;
import org.jetlinks.core.message.function.FunctionInvokeMessage;
import org.jetlinks.core.message.function.FunctionInvokeMessageReply;
import org.jetlinks.core.message.function.FunctionParameter;
import org.xurui.sxl.protocol.cache.ConcurrentMapCache;
import org.xurui.sxl.protocol.command.CmdCodec;
import org.xurui.sxl.protocol.enums.CommandEnum;
import org.xurui.sxl.protocol.utils.BinaryUtils;
import org.xurui.sxl.protocol.utils.NumberUtils;
import org.xurui.sxl.protocol.utils.SxlMessageUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 设置服务器 IP 地址、端口号
 */
@Slf4j
public class CmdCodec_S23 implements CmdCodec {
    @Override
    public boolean supportsCmd(String cmd) {
        return CommandEnum.S23.name().equals(cmd);
    }

    @Override
    public boolean supportsRelayCmd() {
        return true;
    }

    @Override
    public List<DeviceMessage> parsePayload(String payload, FromDeviceMessageContext context) {
        //设备回复格式：*XX,YYYYYYYYYYYYYYY,V4,S23,seq,para,HHMMSS,S,latitude,D,longitude,G,speed,pdop,DDMMYY,tracker_status#
        //设备回复示例：*TJ,7893267561,V4,S23,130305,220,231,193,233,12345,5,130506,A,2212.8745,N,11346.6574,E,14.28,2.8,220902,FFFFFFFF#
        FunctionInvokeMessageReply report = FunctionInvokeMessageReply.create();
        String[] payloadArr = payload.replaceAll("\\*","").split(",");
        String deviceId = payloadArr[1];
        report.setDeviceId(deviceId);
        Object messageIdObj = ConcurrentMapCache.getInstance().getAndRemove(deviceId+"_"+CommandEnum.S23.name()+"_"+payloadArr[4]);
        String messageId = messageIdObj==null?null:messageIdObj.toString();
        if(messageId==null){
            messageId = deviceId+"_"+payloadArr[4];
        }

        report.setFunctionId(CommandEnum.S23.name());
        report.setMessageId(messageId);
        report.setTimestamp(System.currentTimeMillis());
        String para=payloadArr[5]+","+payloadArr[6]+","+payloadArr[7]+","+payloadArr[8]+","+payloadArr[9]+","+payloadArr[10];

        Map<String, Object> properties = new HashMap<>();
        properties.put("para",para);
        properties.put("uptime",payloadArr[11]);
        properties.put("s",payloadArr[12]);
        properties.put("latitude",BinaryUtils.getWgs84LonLat(payloadArr[13],"lat"));
        properties.put("d",payloadArr[14]);
        properties.put("longitude",BinaryUtils.getWgs84LonLat(payloadArr[15],"lon"));
        properties.put("g",payloadArr[16]);
        properties.put("speed", NumberUtils.parseDouble(payloadArr[17]));
        properties.put("pdop",NumberUtils.parseDouble(payloadArr[18]));
        properties.put("upday", payloadArr[19]);
        String trackerStatusHex = payloadArr[20];


        Map<String,Object> trackerStatusMap = parseTrackerStatus(trackerStatusHex);
        properties.put("trackerstatus",trackerStatusMap);
        report.setOutput(properties);

        //TODO 更新状态
        return genDeviceMessage(report);
    }

    @Override
    public EncodedMessage encodeMessage(CommonDeviceMessage message,String zzs) {
        //平台下发消息
        //格式：*XX,YYYYYYYYYYYYYYY,S23,HHMMSS,IP_addr,Port,Redial_Times#
        //例子：*TJ,7893267561,S23,130305,220,231,193,233,12345,5#
        //参数说明：IP_addr 服务器 IP 地址，地址分隔符要求一定是逗号，不能用圆点，IP 地址与端口号之间也必须是逗号。
        //参数说明：Port 服务器端口号（0-65535）
        //参数说明：Redial_Times 连接不成功的重连次数，范围：5-254，Redial_Times <5 自动设置为 5，Redial_Times =255 则表示无限次，超过 255 按 255 取模。超过重连次数不再切换，还原到原先的 IP 地址。
        if(message instanceof FunctionInvokeMessage){
            FunctionInvokeMessage m = (FunctionInvokeMessage)message;
            List<FunctionParameter> params = m.getInputs();
            Map<String,Object> paramsMap = params.stream()
                .collect(Collectors.toMap(FunctionParameter::getName,FunctionParameter::getValue));
            //获取的IP地址必须是逗号（,）分隔,长度为4
            if(paramsMap.get("ipAddr")!=null && !paramsMap.get("ipAddr").equals("")){
                String[] ipAddrs=paramsMap.get("ipAddr").toString().split(",");
                if(ipAddrs.length==4){
                    String port="0";
                    if(paramsMap.get("port")!=null && !paramsMap.get("port").equals("")){
                        port=paramsMap.get("port").toString();
                    }
                    String redialTimes="5";
                    if(paramsMap.get("redialTimes")!=null && !paramsMap.get("redialTimes").equals("")){
                        redialTimes=paramsMap.get("redialTimes").toString();
                    }
                    String time = SxlMessageUtils.getTimeHHMMSS();//DateFormatUtils.format(new Date(),"HHmmss");
                    /*StringBuffer sb = new StringBuffer();
                    sb.append("*");
                    sb.append(zzs);//TODO 需要修改成根据设备动态加载
                    sb.append(",");
                    sb.append(message.getDeviceId());
                    sb.append(",");
                    sb.append(CommandEnum.S23.name());
                    sb.append(",");
                    sb.append(time);
                    sb.append(",");
                    sb.append(paramsMap.get("ipAddr"));
                    sb.append(",");
                    sb.append(port);
                    sb.append(",");
                    sb.append(redialTimes);
                    sb.append("#");*/
                    ConcurrentMapCache.getInstance().set(message.getDeviceId()+"_"+CommandEnum.S23.name()+"_"+time,message.getMessageId(),60*3*1000);
                    //return EncodedMessage.simple(Unpooled.wrappedBuffer(sb.toString().getBytes()));

                    return SxlMessageUtils.SxlCmd.getInstance()
                        .appendAndAddSeparator(zzs)
                        .appendAndAddSeparator(message.getDeviceId())
                        .appendAndAddSeparator(CommandEnum.S23.name())
                        .appendAndAddSeparator(time)
                        .appendAndAddSeparator(paramsMap.get("ipAddr").toString())
                        .appendAndAddSeparator(port)
                        .append(redialTimes).buildEncodeMessage();
                }else{
                    log.error("该参数ipAddr以逗号分隔长度不对");
                    return null;
                }
            }else{
                log.error("该参数ipAddr不能为空");
                return null;
            }

        }else{
            if (log.isDebugEnabled()) {
                log.debug("非FunctionInvokeMessage指令{}消息{}",CommandEnum.WIFISCAN.name(),message);
            }
            return null;
        }



    }
}
